import pygame
from pygame import Vector2
from setting import *
from herobullet import *
from missle import *
vect = pygame.math.Vector2
""" 英雄机的类
基本的调用函数
set_pos(self,x,y) 设置飞机初始位置
set_motion_type(self,type) 设置发射方式
press_move(self) 持续移动
press_fire(self) 持续发射
fire(self) 单击发射
missle_fire(self,angle=0)发射导弹
"""

class Hero(pygame.sprite.Sprite):
    def __init__(self, scene):
        pygame.sprite.Sprite.__init__(self)
        # 默认图像及尺寸
        self.image = pygame.image.load('images/hero/hero.png')
        self.rect = self.image.get_rect()
        #获取 场景、大小、图像的mask方式
        self.main_scene = scene
        self.size = vect(self.rect.width, self.rect.height)
        self.mask = pygame.mask.from_surface(self.image)
        #动起来的速度是 2，设置成零的话，以后就动不了了。
        self.speed = 4
        #飞机的x,y初始速度，不动。
        self.x_speed = 0
        self.y_speed = 0
        #保存子弹的精灵组
        self.bullet_sprite = pygame.sprite.Group()
        #保存跟踪弹的精灵组
        self.missle_sprite = pygame.sprite.Group()
        #子弹等级，默认1
        self.bullet_level = 0
        #子弹的类型，包括图像，攻击力
        self.bullet_type  = 0
        #子弹的发射方式，单、双、三、45角……。。
        self.bullet_motion_type = 0
        # 移动按键储存
        self.key_down_list = []
        #发射按键储存
        self.fire_key_list = []
        #获取当前时间，通过时间差，来确定是否发射
        self.start_time = pygame.time.get_ticks()
        self.missle_start_time = pygame.time.get_ticks()
        #用来设置发射间隔 默认 400毫秒
        self.interval = 400
        #设置导弹发射间隔 默认 1000毫秒
        self.missle_interval = 1000
        self.HP = 100

    #计算飞机位置，精灵组会自动调用
    def update(self):
        """ 
        更新飞机位置
            飞机位置超出 scene时，不进行运算
        """
        #计算飞机的位置
        self.rect.x += self.x_speed
        self.rect.y += self.y_speed
        #限制飞机在场景scene
        if self.rect.x <= 0:
            self.rect.x = 0
        elif self.rect.x > SCENEWIDTH - self.size.x:
            self.rect.x = SCENEWIDTH - self.size.x
        elif self.rect.y <= 0:
            self.rect.y = 0
        elif self.rect.y > SCENEHEIGHT - self.size.y:
            self.rect.y = SCENEHEIGHT - self.size.y
        
        
    def draw(self):
        self.my_font = pygame.font.SysFont('kaiti', 16, True, True)

        hero_info = self.my_font.render('score:' , True,
                                        (255, 0, 0))
        self.main_scene.blit(hero_info, (300, 0))
    #设置飞机位置，场景初始化时用
    def set_pos(self, x, y):
        """ 
        设置飞机位置
            x 左上角x点坐标
            y 左上角y点坐标
        """
        self.rect.x = x
        self.rect.y = y

    def get_pos(self):
        """ 
        返回 vector2的值
            example:
            pos1 = get_pos()
            print(pos1.x ,pos1.y)
        """
        return vect(self.rect.x, self.rect.y)

    #飞机移动，把移动的记录存到列表里，在场景的按键里判断，做出反应
    def move(self, direction):
        """ 
        移动飞机
            direction 方向，可以为string值
            RIGHT
            LEFT
            UP
            DOWN
            example：  move("RIGHT")
        """
        #先把字符串全转换为大写
        # x,y方向上不动的，必须设置成 0
        direction = direction.upper()
        if direction == 'RIGHT':
            self.x_speed = self.speed
            self.y_speed = 0
        elif direction == 'LEFT':
            self.x_speed = -self.speed
            self.y_speed = 0
        elif direction == "UP":
            self.x_speed = 0
            self.y_speed = -self.speed
        elif direction == 'DOWN':
            self.x_speed = 0
            self.y_speed = self.speed
        else:
            pass

    def set_bullet_motion_type(self, type=0):
        """ 设置子弹发射方式
           0 默认值 单个，向上
           1 两个
           2 三个
           3 前方45度角范围内
           4 四周90度角
           5 前方180度角范围内
           6 四周360度角
        """
        self.bullet_motion_type = type

    #设置子弹类型,当吃掉了子弹包后，子弹类型更改
    def set_bullet_type(self,type  = 0):
        """ 子弹的类型,类型不同，图片不同，攻击力不同，默认type  = 0

            type 0~5
        """

        self.bullet_type = type

    # 发射普通子弹，其实只是把子弹存到 sprite里
    def fire(self):
        """ 
        发射普通子弹
            根据设置的 motion_tpye设置不同的发射方式，见 set_motion_tpye函数
            子弹存到 self.bullet_sprite精灵类里
        """
        mus = pygame.mixer.Sound('musics/hero_fire.wav')
        mus.set_volume(4)
        mus.play()
        # 先取得飞机发射点位置，为了方便，用了vect，矩形的 midtop tuple 列如:(200,330)
        fire_pos = vect(self.rect.midtop[0],self.rect.midtop[1])
        #单子弹,用了默认值，后期可以加入子弹的其他属性
        #也可以设置双子弹，三子弹等直线发射的子弹 
        if self.bullet_motion_type == 0:
            bullet = HeroBullet(self.main_scene)
            bullet.set_bullet_type(self.bullet_type)
            #子弹的发射类型，也就是英雄的发射类型
            # 即 type = self.bullet_motion_type
            bullet.set_motion_type(type=0) 
            for v in bullet.bullet_sprite:
                v.set_pos(fire_pos.x - v.rect.width//2,
                          fire_pos.y)
                self.bullet_sprite.add(v)
        # 两个
        elif self.bullet_motion_type == 1:
            bullet = HeroBullet(self.main_scene)
            bullet.set_bullet_type(self.bullet_type)
            bullet.set_motion_type(type=1)
            interval = -self.rect.width//4
            for v in bullet.bullet_sprite:
                # blank = self.size/2
                v.set_pos(fire_pos.x - v.size.x // 2 + interval,
                          fire_pos.y)
                self.bullet_sprite.add(v)
                interval += self.rect.width//2

        # 三个
        elif self.bullet_motion_type == 2:
            bullet = HeroBullet(self.main_scene)
            bullet.set_bullet_type(self.bullet_type)
            bullet.set_motion_type(type=2)
            interval = -self.rect.width/2
            for v in bullet.bullet_sprite:
                v.set_pos(fire_pos.x  - v.size.x // 2 + interval,
                          fire_pos.y)
                self.bullet_sprite.add(v)
                interval += self.rect.width//2
        #向上45度范围发射
        else :
            # self.bullet_motion_type == 3:
            bullet = HeroBullet(self.main_scene)
            bullet.set_bullet_type(self.bullet_type)
            bullet.set_motion_type(self.bullet_motion_type)
            for v in bullet.bullet_sprite:
                v.set_pos(fire_pos.x - v.size.x / 2,
                          fire_pos.y)
                self.bullet_sprite.add(v)
        # elif self.bullet_motion_type == 4:
        #     bullet = HeroBullet(self.main_scene)
        #     bullet.set_bullet_type(self.bullet_type)
        #     bullet.set_motion_type(type=4)
        #     for v in bullet.bullet_sprite:
        #         v.set_pos(fire_pos.x - v.size.x / 2,
        #                   fire_pos.y)
        #         self.bullet_sprite.add(v)
        # # 180度发射
        # elif self.bullet_motion_type == 5:
        #     bullet = HeroBullet(self.main_scene)
        #     bullet.set_bullet_type(self.bullet_type)
        #     bullet.set_motion_type(type=5)
        #     for v in bullet.bullet_sprite:
        #         v.set_pos(fire_pos.x - v.size.x / 2,
        #                   fire_pos.y)
        #         self.bullet_sprite.add(v)
        # #向下360度范围发射
        # elif self.bullet_motion_type == 6:
        #     bullet = HeroBullet(self.main_scene)
        #     bullet.set_bullet_type(self.bullet_type)
        #     bullet.set_motion_type(type=6)
        #     for v in bullet.bullet_sprite:
        #         v.set_pos(fire_pos.x - v.size.x / 2,
        #                   fire_pos.y)
        #         self.bullet_sprite.add(v)
        # else:
        #     pass
    #发射导弹
    def missle_fire(self, angle=0):
        """ 导弹的发射
            angle 默认为零，目前没用
            导弹发射间隔不到时，不发射
            默认发射两枚导弹
        """
        current_time = pygame.time.get_ticks()
        pass_time = current_time - self.missle_start_time
        if  pass_time < self.missle_interval:
            return
        self.missle_start_time = current_time

        # hero_pos = vect(self.rect.x, self.rect.y)
        hero_pos = self.get_pos()
        #加两枚导弹到 sprite里
        missle1 = Missle(self.main_scene)
        missle1.set_pos(hero_pos.x,hero_pos.y)
        missle2 = Missle(self.main_scene)
        missle2.set_pos(hero_pos.x+self.size.x,hero_pos.y)
        self.missle_sprite.add(missle1)
        self.missle_sprite.add(missle2)

    #移动按键按下，存到list里
    def key_down(self, key):
        self.key_down_list.append(key)
    
    #移动按键松开，清空列表，初始化速度
    def key_up(self, key):
        if len(self.key_down_list) != 0:
            try:
                self.key_down_list.remove(key)
                #速度再次初始,speed不能初始，不然动不了了。
                # self.speed  = 0
                self.x_speed = 0
                self.y_speed = 0
            except Exception:
                pass


    # 发射键按下向列表添加 j
    def fire_key_down(self, key):
        self.fire_key_list.append(key)

    # 发射键松开向列表删除 j
    def fire_key_up(self, key):
        if len(self.fire_key_list) != 0:  # 判断是否为空
            try:
                self.fire_key_list.remove(key)
            except Exception:
                raise
   #持续移动
   #如果移动键列表不为零，则根据列表数据，相应移动
    def press_move(self):
        if len(self.key_down_list) != 0:
            if self.key_down_list[0] == pygame.K_a:
                self.move('LEFT')
            elif self.key_down_list[0] == pygame.K_d:
                self.move('RIGHT')
            elif self.key_down_list[0] == pygame.K_w:
                self.move('UP')
            elif self.key_down_list[0] == pygame.K_s:
                self.move("DOWN")
    
    # 按键j不放,持续开火
    def press_fire(self):
        """持续发射子弹
        """
        current_time = pygame.time.get_ticks()
        pass_time = current_time - self.start_time
        if len(self.fire_key_list) != 0 and pass_time > self.interval:
            self.fire()
            self.start_time = current_time
